package resolver

// This file will be automatically regenerated based on the schema, any resolver implementations
// will be copied through when generating and any unknown code will be moved to the end.

import (
	"context"
	"errors"
	"fmt"
	"strconv"

	"mall/service/forum/rpc/forumclient"
	"mall/service/wpgql/api/internal/graph/auth"
	"mall/service/wpgql/api/internal/graph/generated"
	"mall/service/wpgql/api/internal/graph/helper"
	"mall/service/wpgql/api/internal/graph/model"
	"mall/service/wpgql/api/internal/graph/util"
)

const forumTopicSingleError = "could not get topic"
const forumTopicListError = "could not list topics"
const forumPostSingleError = "could not get post"
const forumPostListError = "could not list posts"
const forumLikeSingleError = "could not get like"
const forumLikeListError = "could not list likes"

func (r *forumPostResolver) Comments(ctx context.Context, obj *model.ForumPost, first *int, last *int, after *string, before *string, sorter []*model.ForumCommentConnectionSorter, filter *model.ForumCommentConnectionFilter) (*model.ForumCommentConnection, error) {
	panic(fmt.Errorf("not implemented"))
}

func (r *forumPostResolver) Likes(ctx context.Context, obj *model.ForumPost, first *int, last *int, after *string, before *string, sorter []*model.ForumReactionConnectionSorter, filter *model.ForumReactionConnectionFilter) (*model.ForumReactionConnection, error) {
	panic(fmt.Errorf("not implemented"))
}

func (r *forumTopicResolver) Posts(ctx context.Context, obj *model.ForumTopic, first *int, last *int, after *string, before *string, sorter []*model.ForumPostConnectionSorter, filter *model.ForumPostConnectionFilter) (*model.ForumPostConnection, error) {
	panic(fmt.Errorf("not implemented"))
}

func (r *mutationResolver) CreateForumPost(ctx context.Context, input model.CreateForumPostInput) (*model.ForumPostPayload, error) {
	panic(fmt.Errorf("not implemented"))
}

func (r *mutationResolver) UpdateForumPost(ctx context.Context, id string, input model.UpdateForumPostInput) (*model.ForumPostPayload, error) {
	panic(fmt.Errorf("not implemented"))
}

func (r *mutationResolver) DeleteForumPost(ctx context.Context, id string) (*model.DeleteForumPostPayload, error) {
	panic(fmt.Errorf("not implemented"))
}

func (r *mutationResolver) DeleteForumPosts(ctx context.Context, filter *model.ForumPostConnectionFilter) (*model.DeleteForumPostsPayload, error) {
	panic(fmt.Errorf("not implemented"))
}

func (r *queryResolver) ForumTopic(ctx context.Context, id string) (*model.ForumTopic, error) {
	userId := auth.ForumUserIDFromContext(ctx)

	req := &forumclient.TopicDetailReq{
		VisitorId: int64(userId),
	}

	req.Id = helper.ForumTopicID(id)

	preload, eagerLoad := helper.GetForumTopicPreloads(ctx)
	if preload != "" {
		req.Preload = preload
	}
	if eagerLoad != "" {
		req.EagerLoad = eagerLoad
	}

	res, err := r.svcCtx.ForumRpc.TopicDetail(ctx, req)
	if err != nil {
		return nil, errors.New(forumTopicSingleError)
	}

	return helper.ForumTopicToGraphQL(res), nil
}

func (r *queryResolver) ForumTopics(ctx context.Context, first *int, last *int, after *string, before *string, sorter []*model.ForumTopicConnectionSorter, filter *model.ForumTopicConnectionFilter) (*model.ForumTopicConnection, error) {
	panic(fmt.Errorf("not implemented"))
}

func (r *queryResolver) ForumPost(ctx context.Context, id string) (*model.ForumPost, error) {
	userId := auth.ForumUserIDFromContext(ctx)

	req := &forumclient.PostDetailReq{
		VisitorId: int64(userId),
	}

	req.Id = helper.ForumPostID(id)

	preload, eagerLoad := helper.GetForumPostPreloads(ctx) 
	if preload != "" {
		req.Preload = preload
	}
	if eagerLoad != "" {
		req.EagerLoad = eagerLoad
	}

	res, err := r.svcCtx.ForumRpc.PostDetail(ctx, req)
	if err != nil {
		return nil, errors.New(forumPostSingleError)
	}

	return helper.ForumPostToGraphQL(res), nil
}

func (r *queryResolver) ForumPosts(
	ctx context.Context,
	first *int,
	last *int,
	after *string,
	before *string,
	sorter []*model.ForumPostConnectionSorter,
	filter *model.ForumPostConnectionFilter,
) (*model.ForumPostConnection, error) {
	userId := auth.ForumUserIDFromContext(ctx)

	req := &forumclient.PostListReq{
		VisitorId: int64(userId),
	}

	preload, eagerLoad := helper.GetForumPostNodePreloads(ctx)
	if preload != "" {
		req.Preload = preload
	}
	if eagerLoad != "" {
		req.EagerLoad = eagerLoad
	}

	pagination := util.NewPagination(first, last, after, before,
		r.svcCtx.Config.Query.DefaultAmount, r.svcCtx.Config.Query.MaxAmount)

	sorterMap := helper.GetForumPostConnectionSorterMap(pagination, sorter)
	var reverse bool
	if sorterMap != nil {
		for k, v := range sorterMap {
			switch k {
			case "offset":
				if i, err := strconv.ParseInt(v, 10, 32); err == nil {
					req.Offset = int32(i)
				}
			case "limit":
				if i, err := strconv.ParseInt(v, 10, 32); err == nil {
					req.Limit = int32(i)
				}
			case "sorter":
				req.Sorter = v
			case "reverse":
				if v == "1" {
					reverse = true
				}
			}
		}
	}

	filterMap := helper.GetForumPostConnectionFilterMap(filter)
	if filterMap != nil {
		for k, v := range filterMap {
			switch k {
			case "search":
				req.Search = v
			case "filter":
				req.Filter = v
			case "preFilterEntity":
				req.PreFilterEntity = v
			case "preFilter":
				req.PreFilter = v
			}
		}
	}

	res, err := r.svcCtx.ForumRpc.PostList(ctx, req)
	if err != nil {
		return &model.ForumPostConnection{}, errors.New(forumPostListError)
	}

	if len(res.Data) > 0 {
		var posts []*model.ForumPost
		for _, post := range res.Data {
			posts = append(posts, helper.ForumPostToGraphQL(post))
		}
		connection := helper.GetForumPostConnection(posts,
			res.HasNextPage > 0, res.HasPreviousPage > 0, req.Offset, req.Limit, reverse)
		return connection, nil
	}

	return &model.ForumPostConnection{}, nil
}

func (r *queryResolver) ForumLike(ctx context.Context, id string) (*model.ForumReaction, error) {
	userId := auth.ForumUserIDFromContext(ctx)

	req := &forumclient.ReactionDetailReq{
		VisitorId: int64(userId),
	}

	req.Id = helper.ForumReactionID(id)

	preload, eagerLoad := helper.GetForumReactionPreloads(ctx) 
	if preload != "" {
		req.Preload = preload
	}
	if eagerLoad != "" {
		req.EagerLoad = eagerLoad
	}

	res, err := r.svcCtx.ForumRpc.ReactionDetail(ctx, req)
	if err != nil {
		return nil, errors.New(forumLikeSingleError)
	}

	return helper.ForumReactionToGraphQL(res), nil
}

func (r *queryResolver) ForumLikes(
	ctx context.Context,
	first *int,
	last *int,
	after *string,
	before *string,
	sorter []*model.ForumReactionConnectionSorter,
	filter *model.ForumReactionConnectionFilter,
) (*model.ForumReactionConnection, error) {
	userId := auth.ForumUserIDFromContext(ctx)

	req := &forumclient.ReactionListReq{
		VisitorId: int64(userId),
	}

	preload, eagerLoad := helper.GetForumReactionNodePreloads(ctx)
	if preload != "" {
		req.Preload = preload
	}
	if eagerLoad != "" {
		req.EagerLoad = eagerLoad
	}

	pagination := util.NewPagination(first, last, after, before,
		r.svcCtx.Config.Query.DefaultAmount, r.svcCtx.Config.Query.MaxAmount)

	sorterMap := helper.GetForumReactionConnectionSorterMap(pagination, sorter)
	var reverse bool
	if sorterMap != nil {
		for k, v := range sorterMap {
			switch k {
			case "offset":
				if i, err := strconv.ParseInt(v, 10, 32); err == nil {
					req.Offset = int32(i)
				}
			case "limit":
				if i, err := strconv.ParseInt(v, 10, 32); err == nil {
					req.Limit = int32(i)
				}
			case "sorter":
				req.Sorter = v
			case "reverse":
				if v == "1" {
					reverse = true
				}
			}
		}
	}

	filterMap := helper.GetForumReactionConnectionFilterMap(filter)
	if filterMap != nil {
		for k, v := range filterMap {
			switch k {
			case "search":
				req.Search = v
			case "filter":
				req.Filter = v
			case "preFilterEntity":
				req.PreFilterEntity = v
			case "preFilter":
				req.PreFilter = v
			}
		}
	}

	res, err := r.svcCtx.ForumRpc.ReactionList(ctx, req)
	if err != nil {
		return &model.ForumReactionConnection{}, errors.New(forumLikeListError)
	}

	if len(res.Data) > 0 {
		var likes []*model.ForumReaction
		for _, like := range res.Data {
			likes = append(likes, helper.ForumReactionToGraphQL(like))
		}
		connection := helper.GetForumReactionConnection(likes,
			res.HasNextPage > 0, res.HasPreviousPage > 0, req.Offset, req.Limit, reverse)
		return connection, nil
	}

	return &model.ForumReactionConnection{}, nil
}

// ForumPost returns generated.ForumPostResolver implementation.
func (r *Resolver) ForumPost() generated.ForumPostResolver { return &forumPostResolver{r} }

// ForumTopic returns generated.ForumTopicResolver implementation.
func (r *Resolver) ForumTopic() generated.ForumTopicResolver { return &forumTopicResolver{r} }

type forumPostResolver struct{ *Resolver }
type forumTopicResolver struct{ *Resolver }
